package com.nullpointer.xchat.service;

import java.util.List;

import org.jivesoftware.smack.ConnectionListener;
import org.jivesoftware.smack.SmackException;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smackx.muc.DiscussionHistory;

import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.Bitmap;
import android.media.RingtoneManager;
import android.net.ConnectivityManager;
import android.os.Bundle;
import android.os.IBinder;
import android.provider.Settings;
import android.support.v4.app.NotificationCompat;
import android.support.v4.content.LocalBroadcastManager;
import android.telephony.TelephonyManager;

import com.androidquery.AQuery;
import com.nullpointer.xchat.MainActivity;
import com.nullpointer.xchat.R;
import com.nullpointer.xchat.database.MessagesDataManager;
import com.nullpointer.xchat.object.MessageContent;
import com.nullpointer.xchat.object.MessageContent.MsgType;
import com.nullpointer.xchat.object.RoomType;
import com.nullpointer.xchat.object.UserInfo;
import com.nullpointer.xchat.service.NetworkReceiver.OnNetworkListener;
import com.nullpointer.xchat.utils.Common;
import com.nullpointer.xchat.utils.DataManager;
import com.nullpointer.xchat.utils.KiraGameLog;
import com.quickblox.auth.QBAuth;
import com.quickblox.auth.model.QBSession;
import com.quickblox.chat.QBChatService;
import com.quickblox.chat.QBGroupChat;
import com.quickblox.chat.QBPrivateChat;
import com.quickblox.chat.exception.QBChatException;
import com.quickblox.chat.listeners.QBMessageListener;
import com.quickblox.chat.listeners.QBPrivateChatManagerListener;
import com.quickblox.chat.model.QBChatMessage;
import com.quickblox.core.QBEntityCallbackImpl;
import com.quickblox.core.QBSettings;
import com.quickblox.core.helper.StringifyArrayList;
import com.quickblox.users.QBUsers;
import com.quickblox.users.model.QBUser;

public class ChatService extends Service {

	// UI Name
	public static final String UI_NAME_MAIN = "UI_NAME_MAIN";
	public static final String UI_NAME_CHAT_PRIVATE = "UI_NAME_CHAT_PRIVATE";
	public static final String UI_NAME_SPLASH = "UI_NAME_SPLASH";

	// BROADCAST NAME
	public static final String BROADCAST_NAME_MAIN = "com.kiragame.xchat.changeuimain";
	public static final String BROADCAST_NAME_CHAT_PRIVATE = "com.kiragame.xchat.changeuichatprivate";
	public static final String BROADCAST_NAME_SPLASH = "com.kiragame.xchat.changeuisplash";

	// COMMON CONTROL
	public static final String CONTROL_MESSAGE = "CONTROL_MESSAGE";
	public static final String CONTROL_ACTION = "CONTROL_ACTION";

	// ACTION UI MAIN
	public static final String MAIN_ACTION_NOTIFY_CONNECTION_ONLINE = "MAIN_ACTION_NOTIFY_CONNECTION_ONLINE";
	public static final String MAIN_ACTION_NOTIFY_CONNECTION_OFFLINE = "MAIN_ACTION_NOTIFY_CONNECTION_OFFLINE";

	public static final String MAIN_ACTION_UPDATE_MESSAGES_IN_CHAT_ROOM_FRAGMENT = "MAIN_ACTION_UPDATE_MESSAGES_IN_CHAT_ROOM_FRAGMENT";
	public static final String MAIN_ACTION_UPDATE_MESSAGES_IN_MESSAGE_FRAGMENT = "MAIN_ACTION_UPDATE_MESSAGES_IN_MESSAGE_FRAGMENT";

	public static final String MAIN_ACTION_ON_PRE_UPDATE_PROFILE = "MAIN_ACTION_ON_PRE_UPDATE_PROFILE";
	public static final String MAIN_ACTION_ON_FINISHED_UPDATE_PROFILE = "MAIN_ACTION_ON_FINISHED_UPDATE_PROFILE";

	public static final String MAIN_ACTION_ON_PRE_JOIN_ROOM = "MAIN_ACTION_ON_PRE_JOIN_ROOM";
	public static final String MAIN_ACTION_ON_FINISHED_JOIN_ROOM = "MAIN_ACTION_ON_FINISHED_JOIN_ROOM";

	public static final String MAIN_ACTION_ON_USER_ENTERED_ROOM = "MAIN_ACTION_ON_USER_ENTERED_ROOM";
	public static final String MAIN_ACTION_ON_USER_LEFT_ROOM = "MAIN_ACTION_ON_USER_LEFT_ROOM";

	public static final String MAIN_ACTION_ON_PRE_LOG_OUT = "MAIN_ACTION_ON_PRE_LOG_OUT";
	public static final String MAIN_ACTION_ON_FINISHED_LOG_OUT = "MAIN_ACTION_ON_FINISHED_LOG_OUT";

	public static final String MAIN_ACTION_UPDATE_MESSAGES_IN_CHAT_PRIVATE = "MAIN_ACTION_UPDATE_MESSAGES_IN_CHAT_PRIVATE";
	public static final String MAIN_ACTION_RECEIVE_SAY_HI_REQUEST = "MAIN_ACTION_RECEIVE_SAY_HI_REQUEST";

	public static final String SPLASH_ACTION_ON_PRE_SETUP_SERVER = "SPLASH_ACTION_ON_PRE_SETUP_SERVER";
	public static final String SPLASH_ACTION_ON_FINISHED_SETUP_SERVER = "SPLASH_ACTION_ON_FINISHED_SETUP_SERVER";
	public static final String SPLASH_ACTION_NOTIFY_CONNECTION_ONLINE = "SPLASH_ACTION_NOTIFY_CONNECTION_ONLINE";
	public static final String SPLASH_ACTION_NOTIFY_CONNECTION_OFFLINE = "SPLASH_ACTION_NOTIFY_CONNECTION_OFFLINE";

	// ACTION UI CHAT PRIVATE
	// private QBChatService qbChatService;
	private QBGroupChat currentChatRoom;
	private static ChatService mChatService;
	private static boolean isSetupDone = true;
	// private Context mContext;

	// QuickBlox
	// KEY
	private static final String APP_ID = "17401";
	private static final String AUTH_KEY = "9hRTDs9WePY9msJ";
	private static final String AUTH_SECRET = "HpFVfrbOkeYtKT5";

	// private static final String APP_ID = "17932";
	// private static final String AUTH_KEY = "jpfSBwr5JsmZ6Vd";
	// private static final String AUTH_SECRET = "FR4OPqTHArJUP3Y";

	private static QBUser qbUser = null;
	private final String PASSWORD_DEFAULT = "abcd123456";
	private final String USER_EXIST = "login has already been taken";
	private final String NOT_REGISTER = "Unauthorized";
	private final String HAVE_LOGGED = "already logged";
	private final String NO_RESPONSE = "NoResponseException";
	private LocalBroadcastManager broadcaster;
	public static QBPrivateChat chat = null;

	// private String name;
	// private String status;

	private NetworkReceiver networkReceiver;
	private NotificationManager notificationManager;
	private NotificationCompat.Builder builder;
	private Bitmap stub;

	// AUTO CHAT
	private final String AUTO_CHAT_KEY = "a1ffed7f-fa53-4488-83d8-e7cd9ea8448c";
	private MessageContent autoMessageContent;

	public static final String ONLINE = "online";
	public static final String OFFLINE = "offline";
	public static final String INVISIBLE = "invisible";
	public static final String VISIBLE = "visible";
	public static final String USER = "user";
	public static final String BLOCKED_USER = "blocked";

	public static ChatService getInstance() {
		return mChatService;
	}

	public void setUpChatService() {
		KiraGameLog.d("setUpChatService");
		notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
		builder = new NotificationCompat.Builder(this);
		AQuery aq = new AQuery(this);
		stub = aq.getCachedImage(R.drawable.ic_no_avatar);
		generateDeviceID();
		broadcaster = LocalBroadcastManager.getInstance(this);
	}

	@Override
	public void onCreate() {
		KiraGameLog.d("----------- ChatService onCreate() ------------");
		super.onCreate();
		mChatService = this;
		setUpChatService();
		networkReceiver = new NetworkReceiver();
		networkReceiver.setOnNetworkListener(new OnNetworkListener() {

			@Override
			public void onOnline() {
				notifyConnectionOnline();
				setUpServer();
			}

			@Override
			public void onOffine() {
				notifyConnectionOffline();
			}
		});
		this.registerReceiver(networkReceiver, new IntentFilter(
				ConnectivityManager.CONNECTIVITY_ACTION));

	}

	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {
		return START_STICKY;
	}

	@Override
	public IBinder onBind(Intent intent) {
		return null;
	}

	private void generateDeviceID() {
		if (DataManager.getInstance(this).getDeviceID() == null) {
			String deviceId;
			final TelephonyManager mTelephony = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
			if (mTelephony.getDeviceId() != null) {
				deviceId = mTelephony.getDeviceId(); // *** use for mobiles
			} else {
				deviceId = Settings.Secure.getString(getContentResolver(),
						Settings.Secure.ANDROID_ID); // *** use for tablets
			}

			// String android_id = Secure.getString(this.getContentResolver(),
			// Secure.ANDROID_ID);
			DataManager.getInstance(this).setDeviceID(deviceId);
		}
	}

	public void setUpServer() {
		if (!isSetupDone) {
			return;
		}

		callBackOnPreSetupServer();
		KiraGameLog.d("Checking quickblox setup...");

		QBChatService.setDebugEnabled(false);

		QBSettings.getInstance().fastConfigInit(APP_ID, AUTH_KEY, AUTH_SECRET);
		if (!QBChatService.isInitialized()) {
			QBChatService.init(this);
		}

		// create QB user
		//
		qbUser = new QBUser(DataManager.getInstance(this).getDeviceID(),
				PASSWORD_DEFAULT);

		QBAuth.createSession(new QBEntityCallbackImpl<QBSession>() {
			@Override
			public void onSuccess(QBSession session, Bundle params) {
				KiraGameLog.d("QBAuth.createSession success!");
				QBUsers.signIn(qbUser, new QBEntityCallbackImpl<QBUser>() {
					@Override
					public void onSuccess(QBUser user, Bundle args) {
						KiraGameLog.d("QBUsers.signIn success!");
						DataManager.getInstance(ChatService.this).setUserID(
								user.getId());
						qbUser = user;
						qbUser.setPassword(PASSWORD_DEFAULT);
						loginToChatService(qbUser);
					}

					@Override
					public void onError(List<String> errors) {
						KiraGameLog.d("QBUsers.signIn error! " + errors);
						if (errors.get(0).equals(NOT_REGISTER)) {
							KiraGameLog.d("User not exist... Register now! ");
							registerQuickblox();
						} else {
							callBackOnFinishedSetupServer("SignIn Error: "
									+ errors.toString());
						}
					}
				});
			}

			@Override
			public void onError(List<String> errors) {
				KiraGameLog.e("QBAuth.createSession fail! " + errors);
				callBackOnFinishedSetupServer("Create Session Error: "
						+ errors.toString());
			}
		});
	}

	private void loginToChatService(QBUser qbUser) {
		KiraGameLog.d("loginToChatService...");
		QBChatService.getInstance().login(qbUser, new QBEntityCallbackImpl() {
			@Override
			public void onSuccess() {
				KiraGameLog.d("qbChatService.login success!");
				setUpChatConnection();
			}

			@Override
			public void onError(List errors) {
				if (((String) errors.get(0)).contains(HAVE_LOGGED)) {
					setUpChatConnection();
				} else {
					KiraGameLog.e("qbChatService.login error " + errors);
					callBackOnFinishedSetupServer("Login chat service Error: "
							+ errors.toString());
				}

			}
		});
	}

	protected void registerQuickblox() {
		qbUser = new QBUser(DataManager.getInstance(this).getDeviceID(),
				PASSWORD_DEFAULT);

		UserInfo user = DataManager.getInstance(ChatService.this).getUserInfo();
		qbUser.setWebsite(user.toJson());
		qbUser.setFullName(DataManager.getInstance(ChatService.this)
				.getUserName());
		qbUser.setOldPassword(PASSWORD_DEFAULT);
		StringifyArrayList<String> tags = new StringifyArrayList<String>();
		tags.add(UserInfo.genderText[DataManager.getInstance(ChatService.this)
				.getUserGender().ordinal()]);
		tags.add(USER);
		qbUser.setTags(tags);

		QBUsers.signUpSignInTask(qbUser, new QBEntityCallbackImpl<QBUser>() {
			@Override
			public void onSuccess(QBUser mQBUser, Bundle bundle) {
				KiraGameLog.d("SignUpSignInTask success! " + mQBUser);
				DataManager.getInstance(ChatService.this).setUserID(
						mQBUser.getId());
				qbUser.setId(mQBUser.getId());
				loginToChatService(qbUser);
			}

			@Override
			public void onError(List<String> strings) {
				KiraGameLog.e("SignUpSignInTask fail " + strings);
				callBackOnFinishedSetupServer("Sign In Error: "
						+ strings.toString());
			}
		});

	}

	ConnectionListener connectionListener = new ConnectionListener() {

		@Override
		public void reconnectionSuccessful() {
			KiraGameLog.d("reconnection Successful!");
		}

		@Override
		public void reconnectionFailed(Exception arg0) {
			KiraGameLog.d("connectionListener reconnection Failed");
		}

		@Override
		public void reconnectingIn(int arg0) {
			KiraGameLog.d("connectionListener reconnecting In");
		}

		@Override
		public void connectionClosedOnError(Exception arg0) {
			KiraGameLog.d("connectionListener connection Closed On Error");
		}

		@Override
		public void connectionClosed() {
			KiraGameLog.d("connectionListener connection Closed");
		}

		@Override
		public void authenticated(XMPPConnection arg0) {
			KiraGameLog.d("connectionListener authenticated");

		}

		@Override
		public void connected(XMPPConnection arg0) {
			KiraGameLog.d("connectionListener connected");
		}
	};

	private void setUpChatConnection() {
		// Start sending presences
		try {
			QBChatService.getInstance().startAutoSendPresence(30);
		} catch (SmackException.NotLoggedInException e) {
			e.printStackTrace();
		}
		QBChatService.getInstance().addConnectionListener(connectionListener);
		setUpChatPrivate();
		callBackOnFinishedSetupServer(null);
	}

	// CHAT PRAVITE

	private void setUpChatPrivate() {
		QBChatService.getInstance().getPrivateChatManager()
				.addPrivateChatManagerListener(privateChatManagerListener);
	}

	QBPrivateChatManagerListener privateChatManagerListener = new QBPrivateChatManagerListener() {
		@Override
		public void chatCreated(final QBPrivateChat privateChat,
				final boolean createdLocally) {
			if (!createdLocally) {
				privateChat.addMessageListener(privateChatMessageListener);
			}
		}
	};

	QBMessageListener<QBPrivateChat> privateChatMessageListener = new QBMessageListener<QBPrivateChat>() {
		@Override
		public void processMessage(QBPrivateChat privateChat,
				final QBChatMessage chatMessage) {
			String content = chatMessage.getBody();
			MessageContent messageContent = MessageContent
					.fromJsonToMessageContent(content);
			if (messageContent == null) {
				return;
			}
			Integer sendFrom = messageContent.getFromUserID();
			Integer currentChatID = DataManager.getInstance(ChatService.this)
					.getCurrentChatUserId();
			Integer currentUserId = DataManager.getInstance(ChatService.this)
					.getUserID();
			if (DataManager.getInstance(ChatService.this).getBlockUsers()
					.contains(sendFrom)
					|| currentUserId.equals(sendFrom)) {
				// BlockUser
				return;
			}

			if (messageContent.getMsgType() == MsgType.SAY_HI_REQUEST) {
				receiveSayHiRequest(content);
			} else if (messageContent.getMsgType() == MsgType.SEND_TYPING
					|| messageContent.getMsgType() == MsgType.SEND_STOP_TYPING) {
				if (currentChatID != null && currentChatID.equals(sendFrom)) {
					updateMessagesInChatActivity(content);
				}
			} else if (messageContent.getMsgType() == MsgType.CHECK_USER_ONLINE
					|| messageContent.getMsgType() == MsgType.USER_ONLINE
					|| messageContent.getMsgType() == MsgType.CHECK_FRIEND_ONLINE
					|| messageContent.getMsgType() == MsgType.FRIEND_ONLINE) {
				updateMessagesInChatActivity(content);
			} else {
				if (currentChatID != null && currentChatID.equals(sendFrom)) {
					updateMessagesInChatActivity(content);
				} else {
					updateMessagesInMessageFragment(content);
				}
				if (DataManager.getInstance(ChatService.this).isShowNotify()) {
					showNotify(messageContent);
				}
				MessagesDataManager.getInstance(ChatService.this)
						.insertMessage(Integer.toString(sendFrom),
								messageContent);
			}
		}

		@Override
		public void processError(QBPrivateChat privateChat,
				QBChatException error, QBChatMessage originMessage) {

		}

		@Override
		public void processMessageDelivered(QBPrivateChat privateChat,
				String messageID) {

		}

		@Override
		public void processMessageRead(QBPrivateChat privateChat,
				String messageID) {
		}
	};

	public void sendMessage(int toUser, String message, MsgType msgType,
			boolean isShowMsg) {
		if (!isLogin()
				|| QBChatService.getInstance().getPrivateChatManager() == null) {
			setUpServer();
			return;
		}
		try {
			QBPrivateChat privateChat = QBChatService.getInstance()
					.getPrivateChatManager().getChat(toUser);
			if (privateChat == null) {
				privateChat = QBChatService.getInstance()
						.getPrivateChatManager()
						.createChat(toUser, privateChatMessageListener);
			}
			MessageContent msg = new MessageContent();
			msg.setFromUserID(DataManager.getInstance(this).getUserID());
			msg.setName(DataManager.getInstance(this).getUserName());
			msg.setMsgType(msgType);
			msg.setContent(message);

			privateChat.sendMessage(msg.toJson());
			if (isShowMsg
					&& (msgType == MsgType.IMAGE || msgType == MsgType.TEXT)) {
				updateMessagesInChatActivity(msg.toJson());
				MessagesDataManager.getInstance(ChatService.this)
						.insertMessage(Integer.toString(toUser), msg);
			}

		} catch (XMPPException e) {
			KiraGameLog.d("send message fail: " + e.getMessage());
			e.printStackTrace();
		} catch (SmackException.NotConnectedException e) {

		}
	}

	public void leaveChat() {
		try {
			QBChatService
					.getInstance()
					.getPrivateChatManager()
					.removePrivateChatManagerListener(
							privateChatManagerListener);
		} catch (Exception e) {
			e.printStackTrace();
		}

	}

	// CHAT ROOM
	public void sendMessageChatRoom(String message, MsgType msgType) {
		if (!isLogin() || currentChatRoom == null) {
			// setUpServer();
			return;
		}

		try {
			MessageContent msg = new MessageContent();
			msg.setFromUserID(DataManager.getInstance(this).getUserID());
			msg.setName(DataManager.getInstance(this).getUserName());
			msg.setContent(message);
			msg.setMsgType(msgType);
			currentChatRoom.sendMessage(msg.toJson());
		} catch (XMPPException e) {
			KiraGameLog.d("send message to chat room fail: " + e.getMessage());
			e.printStackTrace();
		} catch (SmackException.NotConnectedException e) {
			KiraGameLog.d("send message to chat room fail: " + e.getMessage());
			e.printStackTrace();
		} catch (IllegalStateException e) {
			KiraGameLog.d("send message to chat room fail: " + e.getMessage());
			e.printStackTrace();
		}
	}

	public void joinroom(String roomID, final boolean isNoticeFail) {
		KiraGameLog.d("Room joining...");
		callBackOnPreJoinRoom();
		leaveRoom();
		DiscussionHistory history = new DiscussionHistory();
		history.setMaxStanzas(20);
		if (!isLogin()
				|| QBChatService.getInstance().getGroupChatManager() == null) {
			setUpServer();
			return;
		}
		currentChatRoom = QBChatService.getInstance().getGroupChatManager()
				.createGroupChat(roomID);
		currentChatRoom.join(history, new QBEntityCallbackImpl() {
			@Override
			public void onSuccess() {
				// add listeners
				KiraGameLog.d("join room sucess");
				currentChatRoom.addMessageListener(groupChatQBMessageListener);
				sendOnlineStatusToRoom();
				callBackOnFinishedJoinRoom(null);
			}

			@Override
			public void onError(final List list) {
				KiraGameLog.d("join room error " + list);
				if (isNoticeFail) {
					callBackOnFinishedJoinRoom("Join room error...");
				} else {
					callBackOnFinishedJoinRoom(null);
				}
			}
		});
	}

	QBMessageListener<QBGroupChat> groupChatQBMessageListener = new QBMessageListener<QBGroupChat>() {
		@Override
		public void processMessage(final QBGroupChat groupChat,
				final QBChatMessage chatMessage) {
			String content = chatMessage.getBody();
			updateMessageInChatRoomFragment(content);
		}

		@Override
		public void processError(final QBGroupChat groupChat,
				QBChatException error, QBChatMessage originMessage) {

		}

		@Override
		public void processMessageDelivered(QBGroupChat groupChat,
				String messageID) {
			// never be called, works only for 1-1 chat
		}

		@Override
		public void processMessageRead(QBGroupChat groupChat, String messageID) {
			// never be called, works only for 1-1 chat
		}

	};

	public void sendOnlineStatusToRoom() {
		if (DataManager.getInstance(this).getInvisibleSetting()) {
			return;
		}
		sendMessageChatRoom(DataManager.getInstance(ChatService.this).getUser()
				.toJson(), MsgType.ONLINE);
	}

	public void sendOfflineStatusToRoom() {
		sendMessageChatRoom("", MsgType.OFFLINE);
	}

	public void leaveRoom() {
		if (currentChatRoom != null) {
			sendOfflineStatusToRoom();
			try {
				currentChatRoom.leave();
			} catch (SmackException.NotConnectedException nce) {
				KiraGameLog.d("Leave room error!");
				nce.printStackTrace();
			} catch (XMPPException e) {
				KiraGameLog.d("Leave room error!");
				e.printStackTrace();
			}
			currentChatRoom.removeMessageListener(groupChatQBMessageListener);
			currentChatRoom = null;
		}
	}

	// PROFILE
	public void updateProfile(boolean isOnline, boolean isInvisible,
			RoomType room) {
		callBackOnPreUpdateProfile();
		if (!isLogin()) {
			setUpServer();
			return;
		}
		UserInfo user = DataManager.getInstance(ChatService.this).getUserInfo();
		qbUser.setWebsite(user.toJson());
		qbUser.setFullName(DataManager.getInstance(ChatService.this)
				.getUserName());
		qbUser.setOldPassword(PASSWORD_DEFAULT);
		StringifyArrayList<String> oldTags = qbUser.getTags();
		StringifyArrayList<String> tags = new StringifyArrayList<String>();
		tags.add(UserInfo.genderText[DataManager.getInstance(ChatService.this)
				.getUserGender().ordinal()]);
		if (isOnline) {
			tags.add(ONLINE);
		} else {
			tags.add(OFFLINE);
		}
		if (isInvisible) {
			tags.add(INVISIBLE);
		} else {
			tags.add(VISIBLE);
		}
		tags.add(Common.listRoomTag[room.ordinal()]);
		if (oldTags.contains(BLOCKED_USER)) {
			tags.add(BLOCKED_USER);
		} else {
			tags.add(USER);
		}
		qbUser.setTags(tags);
		qbUser.setOldPassword(PASSWORD_DEFAULT);
		qbUser.setCustomData(user.toJson());

		QBUsers.updateUser(qbUser, new QBEntityCallbackImpl<QBUser>() {
			@Override
			public void onSuccess(QBUser qbuser, Bundle args) {
				KiraGameLog.d("UpdateProfile successful");
				callBackOnFinishedUpdateProfile(null);
			}

			@Override
			public void onError(List<String> errors) {
				KiraGameLog.d("UpdateProfile Errors " + errors);
				callBackOnFinishedUpdateProfile("Update Profile error: "
						+ errors.toString());
			}
		});
	}

	public void logOut() {
		try {
			exit();
			if (isLogin()) {
				QBChatService.getInstance().stopAutoSendPresence();
				QBChatService.getInstance().removeConnectionListener(
						connectionListener);
				leaveRoom();
				leaveChat();

				QBChatService.getInstance().logout(new QBEntityCallbackImpl() {

					@Override
					public void onSuccess() {
						// success
						QBChatService.getInstance().destroy();
						callBackOnFinishedLogOut(null);
						stopSelf();
					}

					@Override
					public void onError(final List list) {
						KiraGameLog.d("Log out error: " + list);
						callBackOnFinishedLogOut("Log out error");
						stopSelf();
					}
				});
			} else {
				stopSelf();
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			stopSelf();
		}

	}

	public void exit() {
		try {
			callBackOnPreLogOut();
			boolean isInvisible = DataManager.getInstance(this)
					.getInvisibleSetting();
			RoomType room = DataManager.getInstance(this).getCurrentRoom();
			updateProfile(false, isInvisible, room);
			MessagesDataManager.getInstance(this).deleteAllMessage();
			MessagesDataManager.getInstance(this)
					.deleteHistoryMessageUnMarkFriend();
		} catch (Exception e) {
			e.printStackTrace();
		}

	}

	@Override
	public void onDestroy() {
		KiraGameLog.d("----------- ChatService onDestroy() ------------");
		unregisterReceiver(networkReceiver);
		super.onDestroy();
	}

	protected void notifyConnectionOffline() {
		updateUI(UI_NAME_MAIN, MAIN_ACTION_NOTIFY_CONNECTION_OFFLINE, null);
		updateUI(UI_NAME_SPLASH, SPLASH_ACTION_NOTIFY_CONNECTION_OFFLINE, null);
	}

	protected void notifyConnectionOnline() {
		updateUI(UI_NAME_MAIN, MAIN_ACTION_NOTIFY_CONNECTION_ONLINE, null);
		updateUI(UI_NAME_SPLASH, SPLASH_ACTION_NOTIFY_CONNECTION_ONLINE, null);
	}

	private void updateMessagesInMessageFragment(String content) {
		updateUI(UI_NAME_MAIN, MAIN_ACTION_UPDATE_MESSAGES_IN_MESSAGE_FRAGMENT,
				content);
	}

	private void updateMessagesInChatActivity(String content) {
		updateUI(UI_NAME_MAIN, MAIN_ACTION_UPDATE_MESSAGES_IN_CHAT_PRIVATE,
				content);
	}

	private void updateMessageInChatRoomFragment(String json) {
		updateUI(UI_NAME_MAIN,
				MAIN_ACTION_UPDATE_MESSAGES_IN_CHAT_ROOM_FRAGMENT, json);
	}

	private void receiveSayHiRequest(String content) {
		updateUI(UI_NAME_MAIN, MAIN_ACTION_RECEIVE_SAY_HI_REQUEST, content);
	}

	private void updateUI(String nameUI, String action, String message) {
		Intent intent = null;
		switch (nameUI) {
		case UI_NAME_MAIN:
			intent = new Intent(BROADCAST_NAME_MAIN);
			break;
		case UI_NAME_CHAT_PRIVATE:
			intent = new Intent(BROADCAST_NAME_CHAT_PRIVATE);
			break;
		case UI_NAME_SPLASH:
			intent = new Intent(BROADCAST_NAME_SPLASH);
			break;
		default:
			return;
		}

		intent.putExtra(CONTROL_ACTION, action);
		if (message != null) {
			intent.putExtra(CONTROL_MESSAGE, message);
		}
		broadcaster.sendBroadcast(intent);
	}

	// MAIN CALLBACK

	private void callBackOnPreSetupServer() {
		isSetupDone = false;
		updateUI(UI_NAME_SPLASH, SPLASH_ACTION_ON_PRE_SETUP_SERVER, null);
	}

	private void callBackOnFinishedSetupServer(String error) {
		isSetupDone = true;
		updateUI(UI_NAME_SPLASH, SPLASH_ACTION_ON_FINISHED_SETUP_SERVER, error);
	}

	private void callBackOnPreUpdateProfile() {
		updateUI(UI_NAME_MAIN, MAIN_ACTION_ON_PRE_UPDATE_PROFILE, null);
	}

	private void callBackOnFinishedUpdateProfile(String error) {
		updateUI(UI_NAME_MAIN, MAIN_ACTION_ON_FINISHED_UPDATE_PROFILE, error);
	}

	private void callBackOnPreJoinRoom() {
		updateUI(UI_NAME_MAIN, MAIN_ACTION_ON_PRE_JOIN_ROOM, null);
	}

	private void callBackOnFinishedJoinRoom(String error) {
		updateUI(UI_NAME_MAIN, MAIN_ACTION_ON_FINISHED_JOIN_ROOM, error);
	}

	private void callBackOnUserEnteredRoom(String userID) {
		updateUI(UI_NAME_MAIN, MAIN_ACTION_ON_USER_ENTERED_ROOM, userID);
	}

	private void callBackOnUserLeftRoom(String userID) {
		updateUI(UI_NAME_MAIN, MAIN_ACTION_ON_USER_LEFT_ROOM, userID);
	}

	private void callBackOnPreLogOut() {
		updateUI(UI_NAME_MAIN, MAIN_ACTION_ON_PRE_LOG_OUT, null);
	}

	private void callBackOnFinishedLogOut(String error) {
		updateUI(UI_NAME_MAIN, MAIN_ACTION_ON_FINISHED_LOG_OUT, error);
	}

	private synchronized void showNotify(MessageContent msgContent) {
		if (!DataManager.getInstance(this).getNotificationSetting()) {
			return;
		}
		try {
			final String messageContent = msgContent.getContent();
			final long when = System.currentTimeMillis();
			final String title = msgContent.getName();

			Intent notificationIntent = new Intent(this, MainActivity.class);
			// notificationIntent.putExtra(Common.ExtraKey.USER_NAME,
			// msgContent.getName());
			// notificationIntent.putExtra(Common.ExtraKey.USER_ID,
			// msgContent.getFromUserID());
			DataManager.getInstance(this).setNotifyUserId(
					msgContent.getFromUserID());
			DataManager.getInstance(this).setNotifyUserName(
					msgContent.getName());
			notificationIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP
					| Intent.FLAG_ACTIVITY_SINGLE_TOP);
			// notificationIntent.setAction(Intent.ACTION_MAIN);
			// notificationIntent.addCategory(Intent.CATEGORY_LAUNCHER);
			final PendingIntent intent = PendingIntent.getActivity(this, 0,
					notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);

			showNotification(messageContent, null, title, when, intent, 1);

		} catch (Exception e) {
			e.printStackTrace();
		}

	}

	public synchronized void showNotification(String message, Bitmap icon,
			String title, long when, PendingIntent intent, int id) {
		KiraGameLog.d(String.format("show notication message: %s, title: %s",
				message, title));
		builder.setContentText(message);
		builder.setSmallIcon(R.drawable.ic_launcher);
		builder.setLights(0xFFFF8800, 200, 200);
		builder.setWhen(when);
		if (icon != null) {
			builder.setLargeIcon(icon);
		} else {
			builder.setLargeIcon(stub);
		}
		if (title != null) {
			builder.setContentTitle(title);
		}
		if (intent != null) {
			builder.setContentIntent(intent);
		}
		if (DataManager.getInstance(this).getVibrationSetting()) {
			long[] pattern = { 0, 100 };
			builder.setVibrate(pattern);
		}
		if (DataManager.getInstance(this).getSoundSetting()) {
			builder.setSound(RingtoneManager
					.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION));
		} else {
			builder.setSound(null);
		}
		builder.setAutoCancel(true);
		Notification notification = builder.build();
		notificationManager.notify(id, notification);
	}

	public boolean isLogin() {
		if (!QBChatService.isInitialized()) {
			return false;
		}
		return QBChatService.getInstance().isLoggedIn();
	}

}
